/*
 * Copyright 2008-2009 Nobject.org, All Rights Reserved.
 * 
 * This software is licensed under LGPL license.
 * See terms of license at gnu.org.
 * 
 * For more information,visit:
 * 
 * http://www.nobject.org
 */
package org.nobject.common.code.model.java;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import org.nobject.common.text.WordUtils;

/**
 * Method Model class
 * 
 * @author bianrongjun
 * @version 1.0
 */
public class MethodModel {

	/**
	 * Access Private
	 */
	public static String ACCESSTYPE_PRIVATE = "private";

	/**
	 * Accesstype Public
	 */
	public static String ACCESSTYPE_PUBLIC = "public";

	/**
	 * Accesstype Protected
	 */
	public static String ACCESSTYPE_PROTECTED = "protected";

	/**
	 * Method Access Type
	 */
	private String methodAccessType = ACCESSTYPE_PUBLIC;

	/**
	 * Method Name
	 */
	private String methodName = null;

	/**
	 * Method Comment
	 */
	private String methodComment = null;

	/**
	 * Method Static
	 */
	private boolean methodStatic = false;

	/**
	 * Returntype Void
	 */
	public static String RETURNTYPE_VOID = "void";

	/**
	 * Method Return Type
	 */
	private String methodReturnType = RETURNTYPE_VOID;

	/**
	 * Method Body
	 */
	private String methodBody = null;

	/**
	 * isInterfaceMethod
	 */
	private boolean methodInterface = false;

	/**
	 * isAbstractMethod
	 */
	private boolean methodAbstract = false;

	/**
	 * methodException
	 */
	private String methodException = null;

	/** codeIndent */
	private boolean codeIndent=false;
	
	/** 方法注解类 */
	private List<String> methodAnnnotations=new LinkedList();
	
	/**
	 * Constructor
	 */
	public MethodModel() {

	}

	/**
	 * Constructor
	 * 
	 * @param methodName
	 */
	public MethodModel(String methodName) {
		this(methodName, RETURNTYPE_VOID);
	}

	/**
	 * Constructor
	 * 
	 * @param methodName
	 * @param methodAccessType
	 */
	public MethodModel(String methodName, String methodReturnType) {
		this(methodName, methodReturnType, ACCESSTYPE_PUBLIC);
	}

	/**
	 * Constructor
	 * 
	 * @param methodName
	 * @param methodReturnType
	 * @param methodAccessType
	 */
	public MethodModel(String methodName, String methodReturnType, String methodAccessType) {
		this(methodName, methodReturnType, methodAccessType, false);
	}

	/**
	 * Constructor
	 * 
	 * @param methodName
	 * @param methodReturnType
	 * @param methodAccessType
	 * @param methodStatic
	 */
	public MethodModel(String methodName, String methodReturnType, String methodAccessType, boolean methodStatic) {
		this(methodName, methodReturnType, methodAccessType, methodStatic, null);
	}

	/**
	 * Constructor
	 * 
	 * @param methodName
	 * @param methodReturnType
	 * @param methodAccessType
	 * @param methodStatic
	 * @param methodComment
	 */
	public MethodModel(String methodName, String methodReturnType, String methodAccessType, boolean methodStatic, String methodComment) {
		this.methodAccessType = methodAccessType;
		this.methodName = methodName;
		this.methodStatic = methodStatic;
		this.methodComment = methodComment;
		this.methodReturnType = methodReturnType;
	}

	/**
	 * Method Params
	 */
	private List<ParamModel> params = new LinkedList<ParamModel>();

	/**
	 * Add Param
	 * 
	 * @param param
	 */
	public void addParam(ParamModel param) {
		if (!param.check()) {
			System.err.println("方法参数设置错误,丢弃");
		} else {
			params.add(param);
		}
	}

	/**
	 * addParams
	 * @param params
	 */
	public void addParams(List params) {
		for (Iterator iterator = params.iterator(); iterator.hasNext();) {
			ParamModel param = (ParamModel) iterator.next();
			addParam(param);
		}
	}
	
	
	/**
	 * Get Method Access Type
	 * 
	 * @return
	 */
	public String getMethodAccessType() {
		return methodAccessType;
	}

	/**
	 * Set Method Access Type
	 * 
	 * @param methodAccessType
	 */
	public void setMethodAccessType(String methodAccessType) {
		this.methodAccessType = methodAccessType;
	}

	/**
	 * Get Method Name
	 * 
	 * @return
	 */
	public String getMethodName() {
		return methodName;
	}

	/**
	 * Set Method Name
	 * 
	 * @param methodName
	 */
	public void setMethodName(String methodName) {
		this.methodName = methodName;
	}

	/**
	 * is Method Static
	 * 
	 * @return
	 */
	public boolean isMethodStatic() {
		return methodStatic;
	}

	/**
	 * Set Method Static
	 * 
	 * @param methodStatic
	 */
	public void setMethodStatic(boolean methodStatic) {
		this.methodStatic = methodStatic;
	}

	/**
	 * Get Method Comment
	 * 
	 * @return
	 */
	public String getMethodComment() {
		return methodComment;
	}

	/**
	 * Set Method Comment
	 * 
	 * @param methodComment
	 */
	public void setMethodComment(String methodComment) {
		this.methodComment = methodComment;
	}

	/**
	 * Set Method Body
	 * 
	 * @param methodBody
	 */
	public void setMethodBody(String methodBody) {
		this.methodBody = methodBody;
	}

	/**
	 * Get Method Body
	 * 
	 * @return
	 */
	public String getMethodBody() {
		return methodBody;
	}

	/**
	 * Get Method Return Type
	 * 
	 * @return
	 */
	public String getMethodReturnType() {
		return methodReturnType;
	}

	/**
	 * Set Method Return Type
	 * 
	 * @param methodReturnType
	 */
	public void setMethodReturnType(String methodReturnType) {
		this.methodReturnType = methodReturnType;
	}

	/**
	 * isMethodInterface
	 * 
	 * @return
	 */
	public boolean isMethodInterface() {
		return methodInterface;
	}

	/**
	 * setMethodInterface
	 * 
	 * @param methodInterface
	 */
	public void setMethodInterface(boolean methodInterface) {
		this.methodInterface = methodInterface;
	}

	/**
	 * isMethodAbstract
	 * 
	 * @return
	 */
	public boolean isMethodAbstract() {
		return methodAbstract;
	}

	/**
	 * setMethodAbstract
	 * 
	 * @param methodAbstract
	 */
	public void setMethodAbstract(boolean methodAbstract) {
		this.methodAbstract = methodAbstract;
	}

	/**
	 * Get Params
	 * 
	 * @return
	 */
	public List<ParamModel> getParams() {
		return params;
	}

	/**
	 * getMethodException
	 * 
	 * @return
	 */
	public String getMethodException() {
		return methodException;
	}

	/**
	 * setMethodException
	 * 
	 * @param methodException
	 */
	public void setMethodException(String methodException) {
		this.methodException = methodException;
	}

	/** isCodeIndent */
	public boolean isCodeIndent() {
		return codeIndent;
	}

	/** setCodeIndent */
	public void setCodeIndent(boolean codeIndent) {
		this.codeIndent = codeIndent;
	}

	/**
	 * Check
	 * 
	 * @return
	 */
	private boolean check() {
		if (this.methodName != null && !this.methodName.equals("")) {
			return true;
		} else {
			return false;
		}
	}

	
	public void addAnnotaion(String annotation){
		this.methodAnnnotations.add(annotation);
	}
	
	/**
	 * Generate Method String
	 */
	public String generateMethodString() {
		if (!check()) {
			System.err.println("方法参数设置错误!");
			return null;
		}
		StringBuffer sb = new StringBuffer();

		
		if(this.codeIndent){
			sb.append("\n\t/** ");
			if (this.methodComment != null && !this.methodComment.equals("")) {
				sb.append(this.methodComment);
			} else {
				sb.append(this.methodName);
			}
			sb.append(" */\n");
		}else{
			// 设置注释
			sb.append("\n\n\t/**\n");
			sb.append("\t * ");
			if (this.methodComment != null && !this.methodComment.equals("")) {
				sb.append(this.methodComment);
			} else {
				sb.append(this.methodName);
			}
			sb.append("\n");

			if (params.size() > 0) {
				for (Iterator iterator = params.iterator(); iterator.hasNext();) {
					ParamModel param = (ParamModel) iterator.next();
					sb.append("\t * @param ");
					sb.append(param.getParamName());
					if (param.getParamComment() != null && !param.getParamComment().equals("")) {
						sb.append(" " + param.getParamComment());
					}
					if (iterator.hasNext()) {
						sb.append("\n");
					}
				}
				sb.append("\n");
			}
			sb.append("\t */\n ");
		}
		
		if(this.methodAnnnotations.size()>0){
			for(String annotation:this.methodAnnnotations){
				sb.append("\t"+annotation+"\n");
			}
		}
		
		
		// 设置方法头
		sb.append("\t").append(methodAccessType);
		if (isMethodStatic()) {
			sb.append(" static");
		}

		if (isMethodAbstract()) {
			sb.append(" abstract");
		}

		sb.append(" " + this.methodReturnType);
		sb.append(" " + this.methodName);
		sb.append("(");
		if (params.size() > 0) {
			for (Iterator iterator = params.iterator(); iterator.hasNext();) {
				ParamModel param = (ParamModel) iterator.next();
				if (!param.check()) {
					System.err.println("方法参数设置错误,丢弃");
					continue;
				}
				sb.append(param.getParamType());
				sb.append(" " + param.getParamName());
				if (iterator.hasNext()) {
					sb.append(",");
				}
			}
		}
		sb.append(")");

		if(this.methodException!=null){
			sb.append(" throws "+this.methodException);
		}
		
		if (isMethodInterface() || isMethodAbstract()) {
			sb.append(";\n");
		} else {
			if(this.codeIndent){
				sb.append("{");
				if (this.methodBody != null && !this.methodBody.equals("")) {
					sb.append(this.methodBody.trim());
				}
				sb.append("}");
			}else{
				sb.append("{\n");
				if (this.methodBody != null && !this.methodBody.equals("")) {
					sb.append(this.methodBody);
					sb.append("\n");
				}
				sb.append("\t}");
			}
			
		}

		return sb.toString();
	}

	/**
	 * 生成Set方法
	 * 
	 * @param variable 变量
	 * @return
	 */
	public static MethodModel generateSetMethod(ParamModel paramModel) {
		MethodModel method = new MethodModel("set" + WordUtils.firstToUpperCase(paramModel.getParamName()), MethodModel.RETURNTYPE_VOID, MethodModel.ACCESSTYPE_PUBLIC);
		method.setMethodComment("设置" + paramModel.getParamComment());
		method.setMethodBody("\t\tthis." + paramModel.getParamName() + "=" + paramModel.getParamName() + ";");
		method.addParam(new ParamModel(paramModel.getParamName(), paramModel.getParamType(), paramModel.getParamComment()));
		return method;
	}

	/**
	 * 生成Get方法
	 * 
	 * @param variable 变量
	 * @return
	 */
	public static MethodModel generateGetMethod(ParamModel paramModel) {
		MethodModel method = new MethodModel("get" + WordUtils.firstToUpperCase(paramModel.getParamName()), paramModel.getParamType(), MethodModel.ACCESSTYPE_PUBLIC);
		method.setMethodComment("获取" + paramModel.getParamComment());
		method.setMethodBody("\t\treturn this." + paramModel.getParamName() + ";");
		return method;
	}
	
}
